using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Windows;
namespace MicroMsg.UI.UserContrl
{
	public class CachedObservableCollection<DataType, CtrlType> : IEnumerable, INotifyCollectionChanged, IList<DataType>, ICollection<DataType>, IEnumerable<DataType> where DataType : BaseDataType where CtrlType : DependencyObject
	{
		private int totalSize;
		private int cacheSize;
		private int fetchSize;
		private List<DataType> cacheList;
		private IDataFetcher<DataType> dataFetcher;
		private int firstIndex;
		private int lastIndex;
		private MMListBox mMMListBox;
		public event NotifyCollectionChangedEventHandler CollectionChanged;
		public DataType this[int index]
		{
			get
			{
				return this.method_0(index);
			}
			set
			{
				IListDataItem listDataItem = value;
				if (listDataItem != null)
				{
					listDataItem.FillData(this.cacheList.get_Item(index));
					if (this.mMMListBox != null)
					{
						this.mMMListBox.Refresh<CtrlType>(index);
					}
				}
			}
		}
		public int Count
		{
			get
			{
				return this.cacheList.get_Count();
			}
		}
		public bool IsFixedSize
		{
			get
			{
				throw new NotImplementedException();
			}
		}
		public bool IsReadOnly
		{
			get
			{
				throw new NotImplementedException();
			}
		}
		public bool IsSynchronized
		{
			get
			{
				throw new NotImplementedException();
			}
		}
		public object SyncRoot
		{
			get
			{
				throw new NotImplementedException();
			}
		}
		public ReadOnlyCollection<DataType> GetCurrentDatas()
		{
			return new ReadOnlyCollection<DataType>(this.cacheList);
		}
		public CachedObservableCollection(int totalSize, int cacheSize, int fetchSize, IDataFetcher<DataType> dataFetcher)
		{
			if (dataFetcher == null)
			{
				throw new Exception("IDataFetcher can't be null!");
			}
			if (fetchSize > cacheSize)
			{
				throw new Exception("fetchSize can't bigger than cacheSize!");
			}
			this.totalSize = totalSize;
			this.cacheSize = cacheSize;
			this.fetchSize = fetchSize;
			this.dataFetcher = dataFetcher;
			this.cacheList = new List<DataType>(totalSize);
			for (int i = 0; i < totalSize; i++)
			{
				this.cacheList.Add(default(DataType));
			}
		}
		public void Bind(MMListBox _MMListBox)
		{
			this.mMMListBox = _MMListBox;
			this.mMMListBox.set_ItemsSource(this);
		}
		public void UnBind()
		{
			if (this.mMMListBox != null)
			{
				this.mMMListBox.set_ItemsSource(null);
				this.mMMListBox = null;
			}
		}
		private DataType method_0(int index)
		{
			if (index < 0 || index >= this.totalSize)
			{
				return default(DataType);
			}
			DataType dataType = this.cacheList.get_Item(index);
			if (dataType != null)
			{
				return dataType;
			}
			bool flag;
			if (index == 0)
			{
				flag = true;
			}
			else
			{
				if (index == this.totalSize - 1)
				{
					flag = false;
				}
				else
				{
					DataType dataType2 = this.cacheList.get_Item(index + 1);
					flag = (dataType2 == null);
				}
			}
			int num = this.fetchSize;
			int start;
			if (flag)
			{
				num = Math.Min(this.fetchSize, this.totalSize - index);
				start = index;
			}
			else
			{
				num = Math.Min(this.fetchSize, index + 1);
				start = index + 1 - num;
			}
			List<DataType> list = this.dataFetcher.fetchDatas(start, num);
			if (list == null)
			{
				return default(DataType);
			}
			if (list.get_Count() > num)
			{
				list = list.GetRange(0, num);
			}
			if (flag)
			{
				for (int i = 0; i < list.get_Count(); i++)
				{
					this.cacheList.set_Item(index + i, list.get_Item(i));
				}
				this.lastIndex = index + list.get_Count() - 1;
			}
			else
			{
				for (int j = 0; j < list.get_Count(); j++)
				{
					this.cacheList.set_Item(index - j, list.get_Item(list.get_Count() - j - 1));
				}
				this.firstIndex = index + 1 - list.get_Count();
			}
			int num2 = this.lastIndex - this.firstIndex + 1;
			int num3 = num2 - this.cacheSize;
			if (num3 > 0)
			{
				if (flag)
				{
					for (int k = 0; k < num3; k++)
					{
						this.cacheList.set_Item(this.firstIndex + k, default(DataType));
					}
					this.firstIndex += num3;
				}
				else
				{
					for (int l = 0; l < num3; l++)
					{
						if (this.lastIndex - l > 0 && this.lastIndex - l < this.Count)
						{
							this.cacheList.set_Item(this.lastIndex - l, default(DataType));
						}
					}
					this.lastIndex -= num3;
				}
			}
			return this.cacheList.get_Item(index);
		}
		public void Insert(int newIndex, DataType value)
		{
			if (newIndex >= 0 && newIndex <= this.totalSize)
			{
				this.totalSize++;
				if (newIndex >= this.firstIndex && newIndex <= this.lastIndex)
				{
					this.cacheList.Insert(newIndex, value);
					this.lastIndex++;
				}
				else
				{
					this.cacheList.Insert(newIndex, default(DataType));
				}
				NotifyCollectionChangedEventHandler collectionChanged = this.CollectionChanged;
				if (collectionChanged != null)
				{
					collectionChanged.Invoke(this, new NotifyCollectionChangedEventArgs(0, value, newIndex));
				}
				return;
			}
		}
		public void RemoveAt(int index)
		{
			if (index >= 0 && index <= this.totalSize)
			{
				this.totalSize--;
				DataType dataType = this.cacheList.get_Item(index);
				if (index >= this.firstIndex && index <= this.lastIndex)
				{
					this.lastIndex--;
				}
				this.cacheList.RemoveAt(index);
				NotifyCollectionChangedEventHandler collectionChanged = this.CollectionChanged;
				if (collectionChanged != null)
				{
					collectionChanged.Invoke(this, new NotifyCollectionChangedEventArgs(1, dataType, index));
				}
				return;
			}
		}
		public override string ToString()
		{
			return string.Concat(new object[]
			{
				"ListDataCache(totalSize=",
				this.totalSize,
				",cacheSize=",
				this.cacheSize,
				",fetchSize=",
				this.fetchSize,
				")"
			});
		}
		public int IndexOf(DataType value)
		{
			return this.cacheList.IndexOf(value);
		}
		public IEnumerator<DataType> GetEnumerator()
		{
			return this.cacheList.GetEnumerator();
		}
		IEnumerator IEnumerable.GetEnumerator()
		{
			return this.cacheList.GetEnumerator();
		}
		public void Add(DataType value)
		{
			throw new NotImplementedException();
		}
		public void Clear()
		{
			throw new NotImplementedException();
		}
		public bool Contains(DataType value)
		{
			throw new NotImplementedException();
		}
		public bool Remove(DataType value)
		{
			throw new NotImplementedException();
		}
		public void CopyTo(DataType[] array, int index)
		{
			throw new NotImplementedException();
		}
	}
}
